package com.songminju.sqlsong.exector;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.songminju.sqlsong.exception.SsqlTranslateException;
import com.songminju.sqlsong.exector.SsqlExecutor.CallBack.CallBackEvent;
import com.songminju.sqlsong.orm.OrmManager;

public class DataSourceSsqlExecutor implements SsqlExecutor{

	private Connection conn = null;
	private OrmManager ormManager = null;
	private CallBack<ResultSet> execCallBack = new CallBack<ResultSet>() {
		@Override
		public ResultSet call(CallBackEvent e, ResultSet rs, Exception excp) {
			return rs;
		}
	};
	public DataSourceSsqlExecutor(Connection conn,OrmManager ormManager) {
		this.conn = conn;
		this.ormManager = ormManager;
	}
	
	
	@Override
	public ResultSet exec(String ssql){
		return exec(ssql,execCallBack);
	}

	@Override
	public <T> T exec(String ssql, CallBack<T> call) {
		String sql = ormManager.translateToSql(ssql);
		if(sql == null) {
			return call.call(CallBackEvent.EXCEPTION, null,new SsqlTranslateException());
		}
		
		try(Statement st = conn.createStatement()){
			ResultSet rs = null;
			st.execute(sql);
			rs = st.getResultSet();
			return call.call(CallBackEvent.SUCCESS, rs, null);
		}catch(Exception e) {
			return call.call(CallBackEvent.EXCEPTION, null,e);
		}
		
	}

	@Override
	public ResultSet exec(String ssql, Object... objects){
		return exec(ssql,execCallBack,objects);
	}

	@Override
	public <T> T exec(String ssql, CallBack<T> call, Object... objects) {
		String sql = ormManager.translateToSql(ssql);
		if(sql == null) {
			return call.call(CallBackEvent.EXCEPTION, null,new SsqlTranslateException());
		}
		ResultSet rs = null;
		try(PreparedStatement st = conn.prepareStatement(sql)){
			if(objects != null) {
				for(int i=0;i<objects.length;i++) {
					st.setObject(i+1, objects[i]);
				}
			}
			st.execute(sql);
			rs = st.getResultSet();
			return call.call(CallBackEvent.SUCCESS, rs, null);
		}catch(Exception e) {
			return call.call(CallBackEvent.EXCEPTION, null,e);
		}
	}

	@Override
	public boolean tryBeginTransaction() {
		try {
			conn.setAutoCommit(false);
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public boolean tryCommit() {
		try {
			conn.commit();
			return true;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public void commit() throws SQLException {
		
		conn.commit();
	}

	@Override
	public void rollback() throws SQLException {
		
		conn.rollback();
	}


	@Override
	public void beginTransaction() throws SQLException {
		conn.setAutoCommit(false);
	}


	@Override
	public void close() {
		try {
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
